package com.atguigu.java;

import org.junit.Test;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalAdjuster;
import java.time.temporal.TemporalAdjusters;
import java.util.Date;
import java.util.Set;

/**
 * jdk8中日期时间API测试
 *
 * @author : leimingchao
 * @date Date : 2021年06月20日 11:28
 */
public class JDK8DateTimeTest {

    @Test
    public void testDate() {
        //偏移量
        Date date = new Date(2020 - 1900, 9 - 1, 8);
        //Tue Sep 08 00:00:00 CST 2020
        System.out.println(date);
    }

    /**
     * LocalDate、LocalTime、LocalDateTime
     * 说明：
     * 1.LocalDateTime相较于LocalDate、LocalTime，使用频率要高一些
     * 2.类似于Calendar
     */
    @Test
    public void test() {
        //now():获取当前的日期、时间和日期+时间
        LocalDate localDate = LocalDate.now();
        LocalTime localTime = LocalTime.now();
        LocalDateTime localDateTime = LocalDateTime.now();


        System.out.println(localDate);
        System.out.println(localTime);
        System.out.println(localDateTime);

        //of():设置指定的年，月，日，时，分，秒。没有偏移量
        LocalDateTime localDateTime1 = LocalDateTime.of(2020, 10, 6, 13, 23, 43);
        System.out.println(localDateTime1);

        System.out.println("*******************************");
        //getXxx():获取相关的属性
        System.out.println(localDateTime.getDayOfMonth());
        System.out.println(localDateTime.getDayOfWeek());
        System.out.println(localDateTime.getMonth());
        System.out.println(localDateTime.getMonthValue());
        System.out.println(localDateTime.getMinute());
        System.out.println("*******************************");

        //体现了不可变性
        //withXxx():设置相关的属性
        LocalDateTime localDateTime2 = localDateTime.withDayOfMonth(22);
        System.out.println(localDateTime);
        System.out.println(localDateTime2);
        System.out.println("**************************************");

        //加
        LocalDateTime localDateTime3 = localDateTime.plusMonths(3);
        System.out.println(localDateTime);
        System.out.println(localDateTime3);
        System.out.println("**************************************");
        //减
        LocalDateTime localDateTime4 = localDateTime.minusDays(6);
        System.out.println(localDateTime);
        System.out.println(localDateTime4);


    }

    /**
     * Instant类似于java.util.Date类
     */
    @Test
    public void test2() {
        //now():获取本初子午线对应的标准时间,UTC时区
        Instant instant = Instant.now();
        //2021-06-20T04:40:39.925Z
        System.out.println(instant);

        Instant minus = instant.minus(Duration.ofMinutes(5));
        System.out.println(minus);

        //添加时间的偏移量
        OffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.ofHours(8));
        //2021-06-20T12:44:11.436+08:00
        System.out.println(offsetDateTime);

        //toEpochMilli():获取对应的毫秒数，自1970年1月1日0时0分0秒（UTC）开始的毫秒数 ---->Date类的getTime()
        long milli = instant.toEpochMilli();
        //1624164703749
        System.out.println(milli);

        //ofEpochMilli():通过给定的毫秒数，获取Instant实例---->Date(long millis)
        Instant instant1 = Instant.ofEpochMilli(1624164703749L);
        System.out.println(instant1);
    }

    /**
     * DateTimeFormatter: 格式化与解析日期或时间,类似于SimpleDateFormat
     * 实例化：
     * 方式一： 预定义的标准格式。如：ISO_LOCAL_DATE_TIME;ISO_LOCAL_DATE;ISO_LOCAL_TIME
     * 方式二： 本地化相关的格式。如：ofLocalizedDateTime(FormatStyle.LONG)
     * 方式三： 自定义的格式。如：ofPattern(“yyyy-MM-dd hh:mm:ss”)
     */
    @Test
    public void test3() {
        //方式一： 预定义的标准格式。如：ISO_LOCAL_DATE_TIME;ISO_LOCAL_DATE;ISO_LOCAL_TIME
        DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
        //格式化:日期--->字符串
        LocalDateTime localDateTime = LocalDateTime.now();
        String format = formatter.format(localDateTime);
        System.out.println(localDateTime);
        System.out.println(format);
        //解析：字符串--->日期
        TemporalAccessor parse = formatter.parse("2021-06-20T13:03:20.296");
        System.out.println(parse);
        System.out.println("**************************************************");
        //方式二：
        //本地化相关的格式。如：ofLocalizedDateTime()
        //FormatStyle.LONG / FormatStyle.MEDIUM / FormatStyle.SHORT :适用于LocalDateTime
        DateTimeFormatter formatter1 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG);
        String str2 = formatter1.format(localDateTime);
        //2021年6月20日 下午01时13分08秒
        System.out.println(str2);
        System.out.println("**************************************************");

        //本地化相关的格式。如：ofLocalizedDate()
        //FormatStyle.FULL / FormatStyle.LONG / FormatStyle.MEDIUM / FormatStyle.SHORT : 适用于LocalDate
        DateTimeFormatter formatter2 = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM);
        LocalDate localDate = LocalDate.now();
        //格式化操作
        String str3 = formatter2.format(localDate);
        //2021-6-20
        System.out.println(str3);
        System.out.println("**************************************************");
        //重点：方式三： 自定义的格式。如：ofPattern(“yyyy-MM-dd hh:mm:ss”)
        DateTimeFormatter formatter3 = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");
        //格式化
        String str4 = formatter3.format(LocalDateTime.now());
        System.out.println(str4);
        //解析
        TemporalAccessor accessor = formatter3.parse("2021-06-20 01:20:16");
        System.out.println(accessor);
    }

    /**
     * 测试ZonedDate,ZoneId和ZonedDateTime
     */
    @Test
    public void test4() {
        //ZoneId:类中包含了所有的时区信息
        Set<String> zoneIds = ZoneId.getAvailableZoneIds();
        zoneIds.stream().filter(s -> s.contains("Asia/Shanghai")).forEach(System.out::println);
        System.out.println("****************************************************************");
        //ZoneId.of():获取指定时区的时间
        LocalDateTime localDateTime = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));
        System.out.println(localDateTime);
        LocalDateTime ldt = LocalDateTime.now();
        ZonedDateTime zonedDateTime2 = ldt.atZone(ZoneId.of("Asia/Shanghai"));
        System.out.println(zonedDateTime2);
        System.out.println("****************************************************************");
        //ZonedDateTime.now():获取本地时区的ZonedDateTime对象
        ZonedDateTime zonedDateTime = ZonedDateTime.now();
        //ZonedDateTime:带时区的日期时间
        System.out.println(zonedDateTime);
        System.out.println("****************************************************************");
        //ZonedDateTime的now(ZoneId id):获取指定时区的ZonedDateTime对象
        ZonedDateTime zonedDateTime1 = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));
        System.out.println(zonedDateTime1);
    }

    /**
     * Duration:计算2个"时间"之间的间隔
     * 测试Duration
     */
    @Test
    public void test5() {
        LocalDateTime localDateTime = LocalDateTime.now();
        LocalDateTime localDateTime1 = LocalDateTime.of(2015, 12, 31, 23, 0);
        Duration duration = Duration.between(localDateTime1, localDateTime);
        System.out.println(duration);
        System.out.println(duration.getSeconds());
        System.out.println(duration.toNanos());
        System.out.println(duration.toMillis());
        System.out.println(duration.toDays());
        System.out.println(duration.toMinutes());
        System.out.println(duration.toHours());
        System.out.println("*********************************");
        LocalDateTime startDateTime = LocalDateTime.of(2016, 6, 12, 15, 23, 32);
        LocalDateTime endDateTime = LocalDateTime.of(2017, 6, 12, 15, 23, 32);
        Duration duration1 = Duration.between(startDateTime, endDateTime);
        System.out.println(duration1.toDays());
        System.out.println("*********************************");
        LocalTime start = LocalTime.now();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        LocalTime end = LocalTime.now();
        System.out.println(Duration.between(start, end).toMillis());
    }

    /**
     * Period：计算2个"日期"之间的间隔
     * 测试Period
     */
    @Test
    public void test6() {
        //Period:用于计算两个“日期”间隔，以年、月、日衡量
        LocalDate localDate = LocalDate.now();
        LocalDate localDate1 = LocalDate.of(2028, 3, 18);
        Period period = Period.between(localDate, localDate1);
        System.out.println(period);
        System.out.println(period.getYears());
        System.out.println(period.getMonths());
        System.out.println(period.getDays());
        Period period1 = period.withYears(2);
        System.out.println(period1);
    }

    /**
     * 测试TemporalAdjuster:时间校正器
     */
    @Test
    public void test7() {
        //获取当前日期的下一个周日是哪天？
        TemporalAdjuster temporalAdjuster = TemporalAdjusters.next(DayOfWeek.SUNDAY);
        LocalDateTime localDateTime = LocalDateTime.now().with(temporalAdjuster);
        System.out.println(localDateTime);
        System.out.println("**************************************************");
        //获取下一个工作日是哪天？
        LocalDate date = LocalDate.now().with(s -> {
            LocalDate localDate = (LocalDate) s;
            if (DayOfWeek.FRIDAY == localDate.getDayOfWeek()) {
                return localDate.plusDays(3);
            } else if (DayOfWeek.SATURDAY == localDate.getDayOfWeek()) {
                return localDate.plusDays(2);
            } else {
                return localDate.plusDays(1);
            }
        });
        System.out.println("下一个工作日是：" + date);
    }

    /**
     * 生成当前秒的时间戳
     */
    @Test
    public void test8() {
        LocalDateTime now = LocalDateTime.now();
        long nowSecond = now.toEpochSecond(ZoneOffset.of("+8"));
        System.out.println("当前时间戳：" + nowSecond);
    }

    /**
     * 获取当前时间的毫秒数
     */
    @Test
    public void test9() {
        long currentTimeMillis = System.currentTimeMillis();
        System.out.println("当前时间戳：" + currentTimeMillis);
        LocalDateTime now = LocalDateTime.now();
        long nowMillSecond = now.toInstant(ZoneOffset.of("+8")).toEpochMilli();
        System.out.println("当前时间戳：" + nowMillSecond);
        System.out.println((nowMillSecond - currentTimeMillis) / 1000);
    }
}
